package com.yyr.callmessage.core.global;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.springframework.http.HttpMethod;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class RequestWrapper extends HttpServletRequestWrapper {

    private static final String FORM_CONTENT_TYPE = "application/json";

    private static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";

    //所有参数的map集合
    private Map<String , String[]> params = new HashMap<String, String[]>();
    private byte[] body;


    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        params.putAll(request.getParameterMap());
        if (isGet()) {
            body = new byte[0];
        } else {
            //???
            body = readBytes(request.getInputStream());
        }
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    @Override
    public String getCharacterEncoding() {
        String enc = super.getCharacterEncoding();
        return (enc != null ? enc : DEFAULT_CHARACTER_ENCODING);
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return params;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(params.keySet());
    }

    @Override
    public String getParameter(String name) {
        String[] values = getParameterValues(name);
        if (values != null && values.length > 0) {
            return values[0];
        } else {
            return null;
        }
//        return super.getParameter(name);
    }

    public void addParameter(String name, String value) {
        params.put(name, new String[]{value});
    }

    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }

    public Map<String, Object> getBodyMap() {
        Gson gson = new GsonBuilder().create();
        Map<String, Object> map = gson.fromJson(new String(body), new TypeToken<Map<String, Object>>() {}.getType());
        return map == null ? new HashMap<>() : map;
    }

    public void putBodyParameter(String name, String value) {
        Map<String, Object> map = getBodyMap();
        map.put(name, value);
        Gson gson = new GsonBuilder().create();
        String bodyStr = gson.toJson(map);
        body = bodyStr.getBytes();
    }

    public boolean isGet() {
        return  HttpMethod.GET.matches(getMethod());
        // 标准get是不需要传content-type
//        return (contentType != null && contentType.contains(FORM_CONTENT_TYPE) &&
//                HttpMethod.GET.matches(getMethod()));
    }

    public boolean isDelete() {
        return HttpMethod.DELETE.matches(getMethod());
    }

    public boolean isOptions() {
        return HttpMethod.OPTIONS.matches(getMethod());
    }


    //???
    private static byte[] readBytes(InputStream in) throws IOException {
        BufferedInputStream buff = new BufferedInputStream(in);
        int buffSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);

        byte[] temp = new byte[buffSize];
        int size = 0;
        while ((size = buff.read(temp)) != -1) {
            out.write(temp, 0, size);
        }
        buff.close();
        return out.toByteArray();
    }

}